import java.io.*;
import java.io.FileNotFoundException;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TreeMap;

public class TemperatureData {

	private static long startPoint = 0;
	private static Date date = new Date();
	private static double highestTemp = -1000000;
	private static double lowestTemp = 1000000;
	private static TreeMap<Long, String> highTmp = new TreeMap<Long, String>();
	private static TreeMap<Long, String> lowTmp = new TreeMap<Long, String>();
	private static TreeMap<Long, String> tmpAtTime = new TreeMap<Long, String>();
	private static TreeMap<Long, Integer> humidityAtTime = new TreeMap<Long, Integer>();

	public static String getHighTemperatureByDate(String date) {
		long milliseconds = dateToMillisecond(date, "yyyy-MM-dd");
		return highTmp.get(milliseconds);
	}

	public static String getLowTemperatureByDate(String date) {
		long milliseconds = dateToMillisecond(date, "yyyy-MM-dd");
		return lowTmp.get(milliseconds);
	}

	public static boolean fillHumidityData(String path) {
		FileInputStream fis;
		try {
			fis = new FileInputStream(path);
			InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
			BufferedReader br = new BufferedReader(isr);
			br.readLine();// skip first line
			String s = "";
			while ((s = br.readLine()) != null) {
				int idx = s.indexOf("|");
				if (idx < 0)
					break;
				String s0 = s.substring(0, idx);
				s = s.substring(idx + 1, s.length());
				idx = s.indexOf("|");
				if (idx < 0)
					break;
				s = s.substring(idx + 1, s.length());
				long milliseconds = HourMinuteToMillisecond(s0 + ":00");
				humidityAtTime.put(milliseconds, Integer.valueOf(s));
			}

			long time = HourMinuteToMillisecond("24:00:00");
			humidityAtTime.put(time, humidityAtTime.get((long) 0));
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}

	private static long HourMinuteToMillisecond(String strTime) { // ignore
																	// milliseconds
		int idx = strTime.indexOf(":");
		String hour = strTime.substring(0, idx);
		strTime = strTime.substring(idx + 1, strTime.length());
		idx = strTime.indexOf(":");
		String minute = strTime.substring(0, idx);
		strTime = strTime.substring(idx + 1, strTime.length());
		String second = strTime.substring(0, idx);
		long millisecond = Long.valueOf(hour) * 60 * 60 * 1000
				+ Long.valueOf(minute) * 60 * 1000 + Long.valueOf(second)
				* 1000;
		return millisecond;
	}

	public static boolean fillTemperatureData(String path1, String path2) {
		FileInputStream fis;
		try {
			fis = new FileInputStream(path1);
			InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
			BufferedReader br = new BufferedReader(isr);
			br.readLine();// skip first line
			String s = "";
			while ((s = br.readLine()) != null) {
				// String s = in.nextLine();
				int idx = s.indexOf("|");
				if (idx < 0)
					break;
				String s0 = s.substring(0, idx);
				s = s.substring(idx + 1, s.length());
				idx = s.indexOf("|");
				String s1 = s.substring(0, idx);
				long milliseconds = HourMinuteToMillisecond(s0 + ":00");
				tmpAtTime.put(milliseconds, s1);
				highestTemp = Math.max(highestTemp, Double.valueOf(s1));
				lowestTemp = Math.min(lowestTemp, Double.valueOf(s1));
			}

			long time = HourMinuteToMillisecond("24:00:00");
			tmpAtTime.put(time, tmpAtTime.get((long) 0));
			fis.close();

			fis = new FileInputStream(path2);
			isr = new InputStreamReader(fis, "UTF-8");
			br = new BufferedReader(isr);
			br.readLine();// skip first line
			while ((s = br.readLine()) != null) {
				int idx = s.indexOf("|");
				if (idx < 0)
					break;
				String s0 = s.substring(0, idx);
				String s1 = s.substring(idx + 1, s.length());
				idx = s1.indexOf("|");
				String s2 = s1.substring(0, idx);
				String s3 = s1.substring(idx + 1, s1.length());
				highTmp.put(dateToMillisecond(s0, "yyyy-MM-dd"), s2);
				lowTmp.put(dateToMillisecond(s0, "yyyy-MM-dd"), s3);
			}
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}

	public static double getCorrespondingTemperature(double x, double high1,
			double low1, double high2, double low2) {
		double y = low2 + ((x - low1) / (high1 - low1)) * (high2 - low2);
		return y;
	}

	public static Integer getCurrentHumidity(String tmpDateTime) {
		int idx = tmpDateTime.indexOf(" ");
		String time = tmpDateTime.substring(idx + 1, tmpDateTime.length());
		long milliseconds = HourMinuteToMillisecond(time);
		// System.out.println("Current milliseconds is " + milliseconds);

		long time2 = humidityAtTime.ceilingKey(milliseconds);
		long time1 = humidityAtTime.floorKey(milliseconds);
		// time1 should less than time2
		Integer humidity1 = humidityAtTime.get(time1);
		Integer humidity2 = humidityAtTime.get(time2);

		if (milliseconds == time1)
			return humidity1;
		else if (milliseconds == time2)
			return humidity2;
		else
			return (int) (humidity1 + (humidity2 - humidity1)
					* (milliseconds - time1) / (time2 - time1));
	}

	public static String getCurrentTemperature(String tmpDateTime) {
		// String tmpDateTime = "2011-05-05 02:30:03";
		int idx = tmpDateTime.indexOf(" ");
		String time = tmpDateTime.substring(idx + 1, tmpDateTime.length());
		long milliseconds = HourMinuteToMillisecond(time);
		long time1 = tmpAtTime.floorKey(milliseconds);
		long time2 = tmpAtTime.ceilingKey(milliseconds); // time1 should less
															// than time2
		Double temperature1 = Double.valueOf(tmpAtTime.get(time1));
		Double temperature2 = Double.valueOf(tmpAtTime.get(time2));
		Double retvalue;
		if (milliseconds == time1)
			retvalue = temperature1;
		else if (milliseconds == time2)
			retvalue = temperature2;
		else
			retvalue = (double) (temperature1 + (milliseconds - time1)
					* (temperature2 - temperature1) / (time2 - time1));

		String dateStr = tmpDateTime.substring(0, idx);
		dateStr = getNearestDate(dateStr);
		String highT = getHighTemperatureByDate(dateStr);
		String lowT = getLowTemperatureByDate(dateStr);
		double dhighTemp = Double.valueOf(highT);
		double dlowTemp = Double.valueOf(lowT);

		retvalue = getCorrespondingTemperature(retvalue, highestTemp,
				lowestTemp, dhighTemp, dlowTemp);
		String s = String.format("%.1f", retvalue);
		return s;
	}

	public static String getCurrentDateTime(String dateStr, int step) {

		long milliseconds = date.getHours() * 3600000 + date.getMinutes()
				* 60000 + step * startPoint * 1000;
		startPoint++;
		milliseconds += dateToMillisecond(dateStr, "yyyy-MM-dd");
		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		return dateFormat.format(milliseconds);
	}

	private static long dateToMillisecond(String dateStr, String dataFormat) {
		try {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dataFormat);
			Date date = simpleDateFormat.parse(dateStr);
			return date.getTime();
		} catch (ParseException px) {
			px.printStackTrace();
			return 0;
		}
	}

	private static String millisecondToDate(long milliSeconds) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		return dateFormat.format(milliSeconds);
	}

	public static String getNearestDate(String strDate) {
		int idx = strDate.indexOf("-");
		// String year = strDate.substring(0, idx);
		String s1 = strDate.substring(idx, strDate.length());
		String date1 = "2011" + s1;
		String date2 = "2012" + s1;
		long lldate1 = dateToMillisecond(date1, "yyyy-MM-dd");
		long lldate2 = dateToMillisecond(date2, "yyyy-MM-dd");
		if (highTmp.containsKey(lldate1))
			return date1;
		else if (highTmp.containsKey(lldate2))
			return date2;
		else if (highTmp.ceilingKey(lldate1) != null
				& highTmp.ceilingKey(lldate2) != null) {
			return millisecondToDate(Math.min(highTmp.ceilingKey(lldate1),
					highTmp.ceilingKey(lldate2)));
		} else if (highTmp.floorKey(lldate1) != null
				& highTmp.floorKey(lldate2) != null) {
			return millisecondToDate(Math.min(highTmp.floorKey(lldate1),
					highTmp.floorKey(lldate2)));
		} else
			return "";
	}

}
